//#include "stm32f03x.h"
#include "stm32f0xx_hal.h"
//#include "stdio.h"


#define NOP() __NOP



#define DS1302_CLK_H()	(GPIOB->BSRR=GPIO_PIN_13)
#define DS1302_CLK_L()	(GPIOB->BRR=GPIO_PIN_13)

#define DS1302_RST_H()	(GPIOB->BSRR=GPIO_PIN_12)
#define DS1302_RST_L()	(GPIOB->BRR=GPIO_PIN_12)

#define DS1302_OUT_H()	(GPIOB->BSRR=GPIO_PIN_14)
#define DS1302_OUT_L()	(GPIOB->BRR=GPIO_PIN_14)
											
#define DS1302_IN_X		(GPIOB->IDR&GPIO_PIN_14)

#define Time_24_Hour	0x00
#define Time_Start		0x00

#define DS1302_SECOND	0x80
#define DS1302_MINUTE	0x82
#define DS1302_HOUR		0x84
#define DS1302_DAY		0x86
#define DS1302_MONTH	0x88
#define DS1302_WEEK		0x8A
#define DS1302_YEAR		0x8C
#define DS1302_WRITE	0x8E
#define DS1302_POWER	0x90

typedef uint8_t u8;


unsigned char uc_Systime[8];

void ReadDS1302Clock(u8 *p);

void DS1302_Configuration(void)
{
	 GPIO_InitTypeDef GPIO_InitStruct = {0};

	 /*Configure GPIO pins : PB12 PB13 PB14 */
	  GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
	  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	  GPIO_InitStruct.Pull = GPIO_PULLUP;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}



static void DelayNOP(uint32_t count)
{
	//while(count--) NOP();
	while(count--) __ASM("NOP");
}


static void DS1302_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	  GPIO_InitStruct.Pin = GPIO_PIN_14;
	  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	  GPIO_InitStruct.Pull = GPIO_PULLUP;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

static void DS1302_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	 GPIO_InitStruct.Pin = GPIO_PIN_14;
	  GPIO_InitStruct.Mode =GPIO_MODE_INPUT ;
	  GPIO_InitStruct.Pull = GPIO_PULLUP;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void DS1302SendByte(uint8_t byte)
{
	uint8_t	i;

	for(i=0x01;i;i<<=1)
	{
		if(byte&i)	DS1302_OUT_H();
		else	DS1302_OUT_L();
		DS1302_CLK_H();
		DelayNOP(50);
		DS1302_CLK_L();
	}
}

u8 DS1302ReceiveByte(void)
{
	uint8_t	i,byte=0;

	for(i=0x01;i;i<<=1)
	{
		if(DS1302_IN_X)	byte |= i;
		DS1302_CLK_H();
		DelayNOP(50);		//����ʱ
		DS1302_CLK_L();
	}
	return(byte);
}

void Write1302(uint8_t addr,uint8_t data)
{
    DS1302_OUT();
	DS1302_RST_L();
	DS1302_CLK_L();
	DS1302_RST_H();
	DelayNOP(100);
	DS1302SendByte(addr);
	DS1302SendByte(data);
	DelayNOP(100);
	DS1302_RST_L();
}

u8 Read1302(uint8_t addr)
{
    u8 data=0;

    DS1302_OUT();
	DS1302_RST_L();
	DS1302_CLK_L();
	DS1302_RST_H();
	DelayNOP(100);
	DS1302SendByte(addr|0x01);
	DS1302_IN();
	data = DS1302ReceiveByte();
	DelayNOP(100);
	DS1302_RST_L();
	return(data);
}

//��ȡʱ�亯��
void DS1302_GetTime(uint8_t *time)
{
//	u8 tmp;
	
	time[0] = Read1302(DS1302_YEAR);
	time[1] = Read1302(DS1302_WEEK);
	time[2] = Read1302(DS1302_MONTH);
	time[3] = Read1302(DS1302_DAY);
	time[4] = Read1302(DS1302_HOUR);
	time[5] = Read1302(DS1302_MINUTE);
	time[6] = Read1302(DS1302_SECOND);	
}

/*
��ȡDS1302�е�RAM
addr:��ַ,��0��30,��31���ֽڵĿռ�
����Ϊ����ȡ������
*/
uint8_t ReadDS1302Ram(uint8_t addr)
{
	u8	tmp,res;

	tmp = (addr<<1)|0xc0;
	res = Read1302(tmp);
	return(res);
}


void WriteDS1302Ram(uint8_t addr,uint8_t data)
{
	u8	tmp;

	Write1302(DS1302_WRITE,0x00);		//�ر�д����
	tmp = (addr<<1)|0xc0;
	Write1302(tmp,data);
	Write1302(DS1302_WRITE,0x80);		//��д����
}

void ReadDSRam(uint8_t *p,uint8_t add,uint8_t cnt)
{
	uint8_t i;
	
	if(cnt>30) return;
	for(i=0;i<cnt;i++)
	{
		*p = ReadDS1302Ram(add+1+i);
		p++;
	}
}

void WriteDSRam(u8 *p,u8 add,u8 cnt)
{
	u8 i;
	
	if(cnt>30) return;
	for(i=0;i<cnt;i++)
	{
		WriteDS1302Ram(add+1+i,*p++);
	}
}

void ReadDS1302ClockConvertDec(u8 *p)
{
	int i;
	ReadDS1302Clock(&uc_Systime[0]);
//	printf("1302\r\n");
//	for(i=0;i<8;i++)
//	{printf("%d ",uc_time[i]); }
//	printf("\r\n");

	//Hex to Dec

	for(i=0;i<7;i++)
	{
		p[i] = uc_Systime[i]/16*10 + uc_Systime[i]%16;
	}

}

void ReadDS1302Clock(u8 *p)
{
	DS1302_OUT();
	DS1302_RST_L();
	DS1302_CLK_L();
	DS1302_RST_H();
	DelayNOP(100);
	DS1302SendByte(0xbf);
	DS1302_IN();
	p[5] = DS1302ReceiveByte();		//秒
	p[4] = DS1302ReceiveByte();		//分
	p[3] = DS1302ReceiveByte();		//时
	p[2] = DS1302ReceiveByte();		//日
	p[1] = DS1302ReceiveByte();		//月
	p[6] = DS1302ReceiveByte();			//周
	p[0] = DS1302ReceiveByte();		//年
	DS1302ReceiveByte();			//保护标志字节
	DelayNOP(100);
	DS1302_RST_L();
}

/*
写时间函数,顺序为:年周月日时分秒
*/
void WriteDS1302Clock(u8 *p)
{
	Write1302(DS1302_WRITE,0x00);		//关闭写保护
	DS1302_OUT();
	DS1302_RST_L();
	DS1302_CLK_L();
	DS1302_RST_H();
	DelayNOP(100);
	DS1302SendByte(0xbe);				//突发模式
	DS1302SendByte(p[5]);				//秒
	DS1302SendByte(p[4]);				//分
	DS1302SendByte(p[3]);				//时
	DS1302SendByte(p[2]);				//日
	DS1302SendByte(p[1]);				//月
	DS1302SendByte(p[6]);				//周，设置成周一，没有使用
	DS1302SendByte(p[0]);				//年
	DS1302SendByte(0x80);				//保护标志字节
	DelayNOP(100);
	DS1302_RST_L();
}

void InitClock(void)
{
	u8	tmp;

	DS1302_Configuration();
	tmp = ReadDS1302Ram(0);
	if(tmp^0xa5)
	{
		WriteDS1302Ram(0,0xa5);
		Write1302(DS1302_WRITE,0x00);		//关闭写保护
		Write1302(0x90,0x03);				//禁止涓流充电
		Write1302(DS1302_HOUR,0x00);		//设置成24小时制
		Write1302(DS1302_SECOND,0x00);		//使能时钟运行
		Write1302(DS1302_WRITE,0x80);		//打开写保护
	}
}

void DecToHex(u8 *p)
{
	int i;
//	50 = 50 + 5*6
//  15 = 15 + 1*6

//	p[0] = p[0]/10 *6 + p[0];
	for(i=0;i<7;i++)
	{
		p[i] = p[i]/10 *6 + p[i];
	}
}

void SyncDS1302Time(u8 *p)
{
		WriteDS1302Clock(p);
//		for(i=0;i<30;i++)
//		{
//			dd1[i] = i;
//			dd2[i] = 0;
//		}
//		WriteDSRam(dd1,0,30);
//		ReadDSRam(dd2,0,30);
}

/*
void TestDS1302(void)
{
	u8 i,tt[7],dd1[30],dd2[30];
	
	DS1302_Configuration();
	InitClock();
	tt[0] = 0x13;
	tt[1] = 0x05;
	tt[2] = 0x23;
	tt[3] = 0x09;
	tt[4] = 0x25;
	tt[5] = 0x00;
	WriteDS1302Clock(tt);
	for(i=0;i<30;i++)
	{
		dd1[i] = i;
		dd2[i] = 0;
	}
	WriteDSRam(dd1,0,30);
	ReadDSRam(dd2,0,30);
	while(1) 
	{
		ReadDS1302Clock(tt);
	}
}
*/
//end

